package com.feng.cloud.system.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.feng.cloud.common.annotation.ControllerEndpoint;
import com.feng.cloud.common.exception.SystemException;
import com.feng.cloud.common.exception.system.SystemStatus;
import com.feng.cloud.common.request.QueryRequest;
import com.feng.cloud.common.response.RestResponse;
import com.feng.cloud.common.response.TableResultResponse;
import com.feng.cloud.common.utils.SystemBrowserInfoUtils;
import com.feng.cloud.system.entity.LoginLog;
import com.feng.cloud.system.entity.SystemUser;
import com.feng.cloud.system.service.LoginLogService;
import com.feng.cloud.system.service.UserService;
import com.wuwenze.poi.ExcelKit;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.security.Principal;
import java.util.List;
import java.util.Map;

/**
 * @ClassName UserController
 * @Description TODO
 * @Author Better Feng
 * @Date 2019/12/18 18:20
 * @Version 1.0
 **/
@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
public class UserController implements IUserController{

    private final UserService userService;
    private final LoginLogService loginLogService;


    /**
     * 导出用户数据
     * @param params Map
     * @param response HttpServletResponse
     */
    @PostMapping("excel")
    @PreAuthorize("hasAuthority('user:export')")
    @ControllerEndpoint(operation = "导出用户数据", exceptionMessage = "导出Excel失败")
    public void export(@RequestParam Map<String, Object> params,HttpServletResponse response) {
        QueryRequest queryRequest = new QueryRequest(params);
        List<SystemUser> users = this.userService.selectListByPage(queryRequest).getRecords();
        ExcelKit.$Export(SystemUser.class, response).downXlsx(users, false);
    }
    /**
     * 校验用户
     * @param username username
     * @param password password
     * @return RestResponse
     */
    @GetMapping("check/{username}")
    public RestResponse<Void> checkPassword(@NotBlank(message = "{required}")
                                                @PathVariable String username,
                                            @RequestParam(required = false) String password) {
        SystemUser user = userService.checkUserByUsernameAndPassword(username, password);
        if (user == null) {
            if (StringUtils.isBlank(password)) {
                return new RestResponse<>(SystemStatus.USER_NOT_EXIST);
            }
            return new RestResponse<>(SystemStatus.PASSWORD_ERROR);
        }
        return new RestResponse<>();
    }

    /**
     * 列表查询
     * @param params Map
     * @return TableResultResponse
     */
    @Override
    @PreAuthorize("hasAuthority('user:view')")
    public TableResultResponse<SystemUser> selectPage(@RequestParam Map<String, Object> params) {
        QueryRequest request = new QueryRequest(params);
        IPage<SystemUser> iPage = userService.selectListByPage(request);
        return new TableResultResponse<>(iPage.getTotal(), iPage.getRecords());
    }

    /**
     * 新增用户
     * @param user SystemUser
     * @return RestResponse<SystemUser>
     */
    @Override
    @PreAuthorize("hasAuthority('user:add')")
    @ControllerEndpoint(operation = "新增用户", exceptionMessage = "新增用户失败")
    public RestResponse<SystemUser> add(SystemUser user) {
        this.userService.save(user);
        return new RestResponse<SystemUser>().data(user);
    }

    /**
     * 修改用户
     * @param user SystemUser
     * @return RestResponse
     */
    @Override
    @PreAuthorize("hasAuthority('user:update')")
    @ControllerEndpoint(operation = "修改用户", exceptionMessage = "修改用户失败")
    public RestResponse<SystemUser> update(@Valid SystemUser user) {
        this.userService.updateUser(user);
        return new RestResponse<SystemUser>().data(user);
    }

    /**
     * 删除用户
     * @param userIds ids
     * @return RestResponse
     */
    @Override
    @PreAuthorize("hasAuthority('user:delete')")
    @ControllerEndpoint(operation = "删除用户", exceptionMessage = "删除用户失败")
    public RestResponse<Void> update(@NotBlank(message = "{required}") String userIds) {
        String[] ids = userIds.split(StringPool.COMMA);
        this.userService.deleteUsers(ids);
        return new RestResponse<>();
    }

    @PutMapping("password/reset")
    @PreAuthorize("hasAuthority('user:reset')")
    @ControllerEndpoint(exceptionMessage = "重置用户密码失败")
    public RestResponse<Void> resetPassword(@NotBlank(message = "{required}") String usernames) {
        String[] usernameArr = usernames.split(StringPool.COMMA);
        this.userService.resetPassword(usernameArr);
        return new RestResponse<>();
    }

    /**
     * 修改用户信息
     * @param user SystemUser
     * @return RestResponse<SystemUser>
     */
    @Override
    @ControllerEndpoint(operation = "修改个人信息",exceptionMessage = "修改个人信息失败")
    public RestResponse<SystemUser> updateUserProfileById(@Valid SystemUser user) {
        int rows = userService.updateUserProfileById(user);
        if (rows < 1) {
            throw new SystemException(SystemStatus.OPERATION_FAILURE);
        }
        return new RestResponse<SystemUser>().data(user);
    }

    /**
     * 修改密码
     * @param principal Principal
     * @param password password
     * @param newPassword newPassword
     * @return RestResponse<Void>
     */
    @PutMapping("password")
    public RestResponse<Void> updatePassword(Principal principal,@NotBlank String password,
                                             @NotBlank String newPassword) {
        String username = principal.getName();
        userService.updatePassword(username,password,newPassword);
        return new RestResponse<>();
    }

    /**
     * 获取当前用户信息
     * @param principal Principal
     * @return Principal
     */
    @GetMapping("info")
    public RestResponse<SystemUser> currentUser(Principal principal) {
        return new RestResponse<SystemUser>().data(this.userService.selectUserByName(principal.getName()));
    }

    /**
     * 用户登录成功保存登录日志
     * @param username username
     * @param request HttpServletRequest
     * @return RestResponse
     */
    @GetMapping("success/{username}")
    public RestResponse<Void> loginSuccess(@NotBlank(message = "{required}") @PathVariable String username, HttpServletRequest request) {
        // update last login time
        this.userService.updateLoginTime(username);
        // save login log
        LoginLog loginLog = new LoginLog();
        loginLog.setUsername(username);
        String agent = request.getHeader("user-agent");
        loginLog.setSystem(SystemBrowserInfoUtils.os(agent));
        loginLog.setBrowser(SystemBrowserInfoUtils.browser(agent));
        this.loginLogService.saveLoginLog(loginLog);
        return new RestResponse<>();
    }

    @GetMapping("index/{username}")
    public RestResponse<Map<String, Object>> index(@NotBlank(message = "{required}") @PathVariable String username) {
        return new RestResponse<Map<String, Object>>().data(this.userService.indexData(username));
    }
}
